package com.bblocks.dbmonitor.handler;


import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.bblocks.dbmonitor.annotation.MonitorTable;
import com.bblocks.dbmonitor.config.MonitorTableManager;
import com.bblocks.dbmonitor.config.MonitorTableServiceInfo;
import com.pig4cloud.pig.common.core.util.SpringContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import top.javatool.canal.client.annotation.CanalTable;
import top.javatool.canal.client.context.CanalContext;
import top.javatool.canal.client.handler.EntryHandler;
import top.javatool.canal.client.model.CanalModel;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Optional;

/**
 * 获取到map 对象后转换成sql，
 * 配置canal.server 才启动canal客户端
 * @author yang peng
 * @date 2019/4/1915:19
 */
@ConditionalOnExpression("!'${canal.server:}'.isEmpty()")
@Slf4j
@CanalTable(value = "all")
public class DefaultCanalEntryHandler implements EntryHandler<Map<String, String>> {

    @Lazy
    @Resource
    MonitorTableManager monitorTableManager;


    @Override
    public void insert(Map<String, String> map) {
        if(log.isDebugEnabled())
            log.debug("增加 {}", map);
        CanalModel model = CanalContext.getModel();
        String database = model.getDatabase();
        String table = model.getTable();
        execute(database,table,1,map,null);
    }

    @Override
    public void update(Map<String, String> before, Map<String, String> after) {
        if(log.isDebugEnabled()) {
            log.debug("修改 before {}", before);
            log.debug("修改 after {}", after);
        }
        CanalModel model = CanalContext.getModel();
        String database = model.getDatabase();
        String table = model.getTable();
        execute(database,table,2,after,before);
    }

    @Override
    public void delete(Map<String, String> map) {
        if(log.isDebugEnabled())
            log.debug("删除 {}", map);
        CanalModel model = CanalContext.getModel();
        String database = model.getDatabase();
        String table = model.getTable();
        execute(database,table,3,map,null);
    }


    /**
     *
     * @param tableName
     * @param type 1=新增，2=修改，3=删除
     * @param current
     * @param before
     */
    public void execute(String dbName,String tableName,int type,Map<String, String> current,Map<String, String> before){
        /**
         * 1、先执行是否实现了自有刷新业务
         * 2、否则执行通用处理器
         */
        MonitorTableServiceInfo monitorTableService = monitorTableManager.getMonitorTableService(dbName,tableName);
        if(monitorTableService == null)
            return;

        MonitorTable monitorTable = monitorTableService.getMonitorTable();
        boolean ret = true;
        if(monitorTableService.getRecordChangedBaseBean() instanceof  RecordChangedBase){//实现了自有业务
                if (type == 1){
                    try {
                        ret = ((RecordChangedBase) monitorTableService.getRecordChangedBaseBean()).saved(current);
                    }catch (Exception e){
                        log.error("执行异常：",e);
                    }
                }else if(type == 2){
                    try {
                        ret = ((RecordChangedBase) monitorTableService.getRecordChangedBaseBean()).updated(before,current);
                    }catch (Exception e){
                        log.error("执行异常：",e);
                    }
                    getId(monitorTable,current).ifPresent(id->{
                        try {
                            ((RecordChangedBase) monitorTableService.getRecordChangedBaseBean()).updatedId(id);
                        }catch (Exception e){
                            log.error("执行异常：",e);
                        }
                    });
                }else{
                    try {
                        ret = ((RecordChangedBase) monitorTableService.getRecordChangedBaseBean()).deleted(current);
                    }catch (Exception e){
                        log.error("执行异常：",e);
                    }
                    getId(monitorTable,current).ifPresent(id->{
                        try {
                            ((RecordChangedBase) monitorTableService.getRecordChangedBaseBean()).deletedId(id);
                        }catch (Exception e){
                            log.error("执行异常：",e);
                        }
                    });
                }
        }

        if( ret ){
            Map<String, RecordChangedHandler> recordChangedHandlerMap = SpringContextHolder
                    .getBeansOfType(RecordChangedHandler.class);
            if(!MapUtil.isEmpty(recordChangedHandlerMap)){
                recordChangedHandlerMap.forEach((k,handler)->{
                    try {
                        if (type == 1) {
                            handler.saved(current, monitorTableService);
                        } else if (type == 2) {
                            handler.updated(before, current, monitorTableService);
                        } else {
                            handler.deleted(current, monitorTableService);
                        }
                    }catch (Exception e){
                        log.error("handler执行异常：",e);
                    }
                });
            }else {
                log.warn("未有注册通用逻辑/未启动(RecordChangedHandler)！");
            }
        }
    }

    /**
     * 获取id值
     * @param monitorTable
     * @param current
     * @return
     */
    private Optional<String> getId(MonitorTable monitorTable,Map<String, String> current){
        String idValue = null;
        String idKey = monitorTable.id();
        if(StrUtil.isNotEmpty(idKey)){
            idValue = current.get(idKey);
        }
        return Optional.ofNullable(idValue);
    }

}
